/**
 * <p>
 * 页面控件是一种管理整张页面上所有ZXT控件的特殊控件, 可以通过页面控件来获得页面上ZXT控件的实例，控制页面的焦点。
 * </p>
 * @class 页面控件类
 * @extends zxt.ui.Composite
 */
zxt.Page = function(){
	zxt.ui.Composite.call(this);
	
	this.PAGE = null;		
	this.LOCALE = "cn";
	this.TOKEN = false;
	this.XSS = false;

	this._components = {};
	this._rorder = [];
	this._forder = null;
	
	this._lock = false;
	this._event = null;
	this._source = null;
	
	this._initDW = null;
	this._state = {};
	
	this.VALIDATE = false;
	
	this._localizer = new zxt.i18n.Localizer();
};

zxt.defineClazz(zxt.Page, zxt.ui.Composite);

/**
 * <p>返回类型</p>
 * 
 * @function
 * @returns {string} "zxt.page"
 */
zxt.Page.prototype.getType = function() {
	return "zxt.page";
};

/**
 * <P>
 * (DataWrapper) [GETTER | SETTER] 页面初始数据
 * </P>
 * @function
 */
zxt.Page.prototype.initDW = function(v){
	if (v === undefined) {	return this._initDW;	};
	this._initDW = v;
};	

/**
 * <p>
 * (DataWrapper) [GETTER | SETTER] 页面翻译器
 * </p>
 * @function
 */

zxt.Page.prototype.localizer = function(v){
	if (v === undefined) {	return this._localizer;	};
	this._localizer = v;
};

/**
 * <p>
 * (string) [GETTER | SETTER] 控件显示模式
 * </p>
 * @function
 */
zxt.Page.prototype.mode = function(v) {
	if (v === undefined) { return this._mode;	};
	this._mode = v;
};


/**
 * <p>
 * (string) [GETTER | SETTER] 焦点切换模式
 * </p>
 * @function
 */
zxt.Page.prototype.focusMode = function(v){
	if (v === undefined) {	return this._focusMode;	}
	this._focusMode = v;
};

/**
 * <p>
 * 获得控件焦点顺序数组
 * </p>
 * @function
 * @param v 控件ID数组
 * @return {array}  控件无鼠标操作顺序数组
 */
zxt.Page.prototype.focusOrder = function(v){
	if(v===undefined){return this._forder;}
	
	if ( !zxt.util.isArray(v) ){
		throw new Error("Focus Order MUST be an array." + v);
	};
	this.clearFocusCurrent();//zxt.ui.Composite.prototype.clearFocusCurrent
	this._forder = v;	
};

/**
 * <p>定义控件的无鼠标操作顺序</p>
 * @function
 * @param arr 无鼠标操作ID数组
 * @return
 */
zxt.Page.prototype.orderComponents = function(arr){
	this._forder=arr;
	this.focus(true);//设置控件的焦点
};	

zxt.Page.prototype._order = function(){
	if ( this._forder == null ){
		return this._rorder;
	};	
	return this._forder;	
};

zxt.Page.prototype.focused = function(v){
	var forder = this._order();
	var fsize = forder.length;
	
	if (v === undefined){
		if(this._focusCurrent==-1) return null;		
		var idx = this._focusCurrent%fsize;			
		return this.getComponent(forder[idx]);
	};
	
	for( var i=0; i<fsize; i++ ){
		if(forder[i]==v.id()){
			this._focusCurrent = i;	
			this.focusMode("TAB");		
			return;
		};
	};
};

/**
 * <p>
 * 设置控件焦点
 * </p>
 * @function
 * @param forward 控制向前or向后访问控件: true:向前,false:向后
 * @return {int} 1:控件焦点设置成功; 0:跳过该控件
 */
zxt.Page.prototype.focus = function(forward){	
	if ( this.focusMode() == "DEFAULT" ){		
		if ( this._focused == 1 ){return 0;};		
		this._focused = 1;		
		this.onFocus();
		return 1;
	};
	
	var orders=this._order();
	var total = orders.length;
	if ( total ==0 ){	return 0;	};
	
	var fwd = forward;	
	if ( zxt.util.notValue(fwd) ) fwd = true;
	
	var idx = 0;
	if (this._focusCurrent != -1) { idx = this._focusCurrent; };

	var ct = true;
	var looptS = idx;
	while(ct){
		idx = (idx + total) % total;
		var _child = this.getComponent(orders[idx]);//获得控件		
		var _fs = _child.focus(fwd);//取得控件的焦点状态 zxt.ui.Widget.prototype.focus
		if ( _fs > 0 ){	return 1; };
		idx = fwd?idx+1:idx-1;
		idx = (idx + total) % total;
		if ( idx == looptS ){//回到起始点，结束
			ct = false;
		};
	};
	return 0;	
};

/**
 * <p>
 * 返回所有已注册的ZXT控件
 * </p>
 * 
 * @function
 * @return {zxt.ui.Widget[]} _w 已注册的ZXT控件的数组
 */
zxt.Page.prototype.components = function(){
	return this._components;
};

/**
 * <p>
 * 根据ID返回已注册的ZXT控件
 * </p>
 * 
 * @function
 * @param {String} id ZXT控件的ID
 * @return {zxt.ui.Widget} _w ID所对应的ZXT控件
 */
zxt.Page.prototype.getComponent = function(id){
	var _w = this._components[id];
	return _w;
};

/**
 * <p>
 * 注册ZXT控件, 使页面控件能够管理该ZXT控件
 * </p>
 * 
 * @function
 * @param {zxt.ui.Widget} component 需注册的ZXT控件
 * @param {String} component 定义ZXT控件的ID
 */
zxt.Page.prototype.register = function(component, id){
	if ( !zxt.util.isUndefined(id) ){
		if ( ! zxt.util.isLengthString(id) ) {
			throw new Error("Component Setted ID Illegal ["+_id+"]");
		};		
		component.id(id);
	};
	var _id = component.id();
	if ( zxt.util.isValue(_id) && ( !zxt.util.isString(_id) ) ) {
		throw new Error("Component Inner ID Type Illegal [" + _id + "]");
	};
	if ( zxt.util.isLengthString(_id) ){
		var _old = this._components[_id];
		if (zxt.util.isValue(_old)){
			throw new Error("Component already exists ["+_id+"]");
		}; 		
		this._components[_id] = component;
		this._rorder.push(_id);
	};
	this.addChild(component);
	component.setParent(this);
	return this;
};


/**
 * <p>删除注册的组件 </p>
 *
 * @function
 * @param {zxt.data.Component} component ZXT组件
 */
zxt.Page.prototype.unregister = function(component){
	delete this._components[component.id()];
	return this;
};

/**
 * <p>删除指定ID的组件</p>
 * 
 * @function
 * @param {String} id ZXT控件的ID
 */
zxt.Page.prototype.unregisterByID = function(id){
	delete this._components[id];
	return this;
};

/**
 * <p>
 * 保存所有已注册的并且继承自zxt.ui.Interactor的控件的状态，即保存控件的value。
 * </p>
 * 
 * @function
 * @return {String[]} state 所有控件value所组成的数组
 */
zxt.Page.prototype.saveState = function(){
	var state = {};
	for(var v in this._components){
		var comp = this.getComponent(v);
		if ( comp.instanceOf(zxt.ui.Interactor) ){
			state[v] = comp.getValue();
		};	
	};
	this._state = state;
	return state;
};

/**
 * <p>
 * 恢复所有已注册的并且继承自zxt.ui.Interactor和zxt.ui.CompositeInteractor的控件的状态，即恢复控件的value。
 * </p>
 * 
 * @function
 * @param {String[]} state 要恢复的所有控件的value所组成的数组
 */
zxt.Page.prototype.restoreState = function(state){
	var _state = state || this._state;	
	for(var v in this._components){
		var comp = this.getComponent(v);
		if ( comp.instanceOf(zxt.ui.Interactor) ){
			comp.setValue(_state[v]);
			comp.render();
		};
	};
	this._state = _state;
};

/**
 * <p>
 * 登记最近一次被触发的事件
 * </p>
 * 
 * @private
 * @function
 * @param {String} e 事件名
 * @param {String} s 事件来源
 */
zxt.Page.prototype.event = function(e, s){
  this._event = e;
  this._source = s;
};

/**
 * <p>
 * 以AJAX方式提交一组ZXT控件的值给后台相应的类和函数处理
 * </p>
 * 
 * @function
 * @param {zxt.data.DataWrapper} data 包含要提交的控件的value数组的zxt.data.DataWrapper对象
 * @param {map} callback 提交结束后的回调处理对象,包含onSuccess和onFailure两个function对象
 * @param {function} callback.onSuccess 提交成功后的处理函数
 * @param {function} callback.onFailure 提交失败后的处理函数
 * @param {String} [method] 后台处理函数的函数名,默认函数名为"事件名$控件ID"
 */
zxt.Page.prototype.commit = function(data, callback, method){
	var _method = method;
	if ( !zxt.util.isAvailable(_method) ){
		_method = this._event + "$" + this._source;
	};	
	EiCommunicator.commit(_method, data, callback, false);//zxt.data.dw.js EiCommunicator
	return _method;
};

/**
 * <p>
 * 以Form方式提交一组ZXT控件的值给后台相应的类和函数处理
 * </p>
 * 
 * @function
 * @param {zxt.data.DataWrapper} data 包含要提交的控件的value数组的zxt.data.DataWrapper对象
 * @param {String} location 提交结束后跳转到目标页面的目录,例如跳转到页面cvs/CVSR.html,location的值为cvs/
 * @param {String} page 提交结束后跳转到目标页面的页面名,例如跳转到页面cvs/CVSR.html,page的值为CVSR.html
 * @param {String} [method] 后台处理函数的函数名,默认函数名为"事件名$控件ID"
 */
zxt.Page.prototype.submit = function(data, location, page, method, target){
	var _method = method;
	if ( !zxt.util.isAvailable(_method) ){
		_method = this._event + "$" + this._source;
	};	
	
	EiCommunicator.submit(location, page, data, _method,target);
};	

/**
 * <p>
 * 键盘消息处理函数
 * </p>
 * 
 * @private
 * @function
 * @param {event.keyCode} keyCode 键盘事件的按键号
 */
zxt.Page.prototype.onKeyDown = function(event){
	if(this._lock){
		return;
	};
	var keyCode = event.keyCode;
	switch(keyCode){
		case 9://TAB键
			if(event.shiftKey){
				this.focus(false);
			}else{
				this.focus(true);
			}
			break;		
		case 40://下方向键
			if (event.ctrlKey){	this.focus(true);};
			break;	
		case 38://上方向键
			if (event.ctrlKey){	this.focus(false); };
			break;		
		case 39://右方向键
			if (event.ctrlKey){	this._enterCurrent(); };
			break;
		case 37://左方向键
			if (event.ctrlKey){	this._leaveCurrent(); };
			break;
		default:
			if(zxt.util.isAvailable(this.focused())){
				if(zxt.util.isFunction(this.focused().onKeyDown)){
					this.focused().onKeyDown(event);
				};
			};
			break;
	};
};

/**
 * <p>
 * 初始化事件
 * </p>
 * @function
 * @private
 * @event
 */
zxt.Page.prototype.initialize = function(){
	var _func = window["onInitialize"];	
	if ( zxt.util.isFunction(_func) ){			
			_func.call(window, this._initDW);
	};	
};

/**
 * <p>递归子控件的值发生变化的事件</p>
 * @function
 * @private
 * @event
 */
zxt.Page.prototype._onChildValueChange = function(child, old, now) {
	var _func = window["onChildValueChange"];	
	if ( zxt.util.isFunction(_func) ){			
			_func.call(window, child, old, now);
	};
};	

/**
 * <p>
 * error事件，当页面上发生验证错误调用该事件
 * </p>
 * @function
 * @private
 * @event
 * @param {String[]} errs 验证错误列表
 */
zxt.Page.prototype.onValidationErrors = function(errs, phase){	
	var _func = window["onErrors"];		
	for( var i =0 ; i<errs.length; i++){
		if ( zxt.util.isFunction(_func) ){			
			_func.call(window, errs[i]);
		};	
	};	
};

/**
 * <p>
 * 将目标key翻译成本地文字
 * </p>
 * 
 * @function
 * @param {String} key 被翻译的key
 * @param {String} [locale] 语言种类，缺省为系统语言
 */
zxt.Page.prototype.translate = function(key, locale){
	return this._localizer.localize(key, locale);
};

/**
 * <p>
 * 将页面国际化
 * </p>
 * 
 * @private
 * @function
 */
zxt.Page.prototype.translateUI = function(){
	var ws = $("div[i18n]");//查找所有含有i18n 属性的 div 元素
	var host = this;
	ws.each( function( idx, dom ){ zxt.dom.i18n(dom); } );		
};

/**
 * <p>
 * 将控件及其子控件国际化
 * </p>
 * 
 * @private
 * @function
 */
zxt.Page.prototype.translateUIWithSub = function(w){
	$zxt.translateUIWithoutSub(w);
	$zxt.translateUIJustSub(w);	
};

/**
 * <p>
 * 将控件国际化但不包括子控件
 * </p>
 * 
 * @private
 * @function
 */
zxt.Page.prototype.translateUIWithoutSub = function(w){
	var ws = $("#"+w);
	var host = this;
	zxt.dom.i18n(ws.get(0));		
};

/**
 * <p>
 * 将子控件国际化
 * </p>
 * 
 * @private
 * @function
 */
zxt.Page.prototype.translateUIJustSub = function(w){
	var ws = $("#" + w + " div[i18n]");
	var host = this;
	ws.each( function( idx, dom ){ zxt.dom.i18n(dom) } );		
};

/**
 * <p>
 * 构建页面上所有ZXT控件
 * </p>
 * 
 * @private
 * @function
 */
zxt.Page.prototype.constructUI = function(){
	var ws = $("div[zxt]");//查找所有含有 zxt 属性的 div 元素
	var host = this;
	ws.each( function( idx, dom ){
		zxt.dom.zxt(dom);
	});	//以每一个匹配的元素作为上下文来执行函数	
};	

/**
 * <p>
 * 构建页面上指定的ZXT控件但不包括其子控件
 * </p>
 * 
 * @private
 * @function
 */
zxt.Page.prototype.constructUIWithoutSub = function(w){
	var ws = $("#"+w);
	var host = this;
	zxt.dom.zxt(ws.get(0));
};

/**
 * <p>
 * 构建页面上指定的ZXT控件的子控件
 * </p>
 * 
 * @private
 * @function
 */
zxt.Page.prototype.constructUIJustSub = function(w){
	var sub = $("#" + w + " div[zxt]");
	var host = this;
	sub.each( function( idx, dom ){	zxt.dom.zxt(dom); } );		
};

/**
 * <p>
 * 构建页面上指定的ZXT控件及其子控件
 * </p>
 * 
 * @private
 * @function
 */
zxt.Page.prototype.constructUIWithSub = function(w){
	$zxt.constructUIWithoutSub(w);
	$zxt.constructUIJustSub(w);
};



/**
 * <p>
 * 页面初始化
 * </p>
 * 
 * @function
 * @param {String} [page] 页面名
 */
zxt.Page.prototype.init = function(page,mode){
	this.initPage(page, mode);//初始化页面对象
	this.translateUI();//国际化
	this.constructUI();//构建页面ZXT控件
	this.initialize();//调用页面的oninitialize()方法
};



/**
 * <p>初始化页面对象</p>
 * @function
 * @private
 * @param page 页面名
 * @param mode 显示模式
 * @return
 */
zxt.Page.prototype.initPage = function(page, mode){
	if ( zxt.util.isLengthString(page) ){	this.PAGE = page; };
	if ( zxt.util.isLengthString(mode) ){	this._mode = mode; };

	/**	
	var result = location.href.match(/[\?\&]locale=([^\&]+)/);
	this.LOCAL = result && result[1] || "cn";
	**/

	var pwin = zxt.util.getParentWindow(window);//获得父窗口	
	if ( pwin != null ){
		var p = pwin.$zxt;
		this.setParent(p);//设置父控件
		this.localizer().parent(p.localizer());//设置父窗口页面的页面翻译器
	};		
};


/**
 * <p>构建指定控件ID的第一个DOM节点元素</p>
 * @function
 * @param w  控件ID
 * @return
 */
zxt.Page.prototype.constructElement = function(w){
	var ws = $("#"+w);
	zxt.dom.zxt(ws.get(0), true);//构建ws的第一个DOM节点
};

/**
 * <p>构建指定的子空件</p>
 * @function
 * @param w 指定的子控件的ID
 * @param option 选择条件 0:正常加载，1：延迟加载，2：重新加载
 * @return 
 */
zxt.Page.prototype.constructChildren = function(w, option){
	var opt = option || 0;
	var sub = $("#" + w + " div[zxt]");
	sub.each(
		function( idx, dom ){
			if( opt == 0 ){
				zxt.dom.zxt(dom);	//创建ZXT控件				
			} else if ( opt ==1 ){
				zxt.dom.lazyDom(dom); //延迟 加载ZXT控件
			}	else if (opt==2){
				zxt.dom.zxt(dom, true); //重新加载ZXT控件
			}	 
		} 
	);		
};

/**
 * <p>
 * 初始化指定控件但不包括其子控件
 * </p>
 * 
 * @function
 */
zxt.Page.prototype.initWithoutSub = function(page, widget, mode){
	
	preparePage(this, page, mode);
	
	this.translateUIWithoutSub(widget);
	this.constructUIWithoutSub(widget);
};

/**
 * <p>
 * 初始化指定控件的子控件
 * </p>
 * 
 * @function
 */
zxt.Page.prototype.initJustSub = function(page, widget, mode){
	preparePage(this, page, mode);
	
	this.translateUIJustSub(widget);
	this.constructUIJustSub(widget);
};

/**
 * <p>
 * 初始化指定控件及其子控件
 * </p>
 * 
 * @function
 */
zxt.Page.prototype.initWithSub = function(page, widget, mode){
	preparePage(this, page, mode);
	
	this.translateUIWithSub(widget);
	this.constructUIWithSub(widget);
};

function preparePage(host, page, mode){
	
	if ( zxt.util.isLengthString(page) ){	host.PAGE = page; };
	if ( zxt.util.isLengthString(mode) ){	host._mode = mode; };
	
	var pwin = zxt.util.getParentWindow(window);	
	if ( pwin != null ){
		var p = pwin.$zxt;
		host.setParent(p);
		host.localizer().parent(p.localizer());
	};
}

/**
 * <p>锁定页面屏蔽输入</p>
 * @param time 延时时间，单位毫秒
 * @return
 */
zxt.Page.prototype.lock = function(time){
	if(zxt.util.isNumber(time)){
		 var unlock = function(){
            $zxt.unlock();
        };
        pageLockTimmer = window.setTimeout(unlock, time);//
	};
	this._lock = true;
	if(!this._overlay){
		window.$("body").append("<div class='zxt-lockOverlay'></div>");
		this._overlay = $(".zxt-lockOverlay");
	}else{
		this._overlay.show();
	};
};

/**
 * <p>解除锁定</p>
 * @return
 */
zxt.Page.prototype.unlock = function(){
	this._lock = false;
	this._overlay.hide();
};

zxt.Page.prototype.validate = function(clist){
	//var l = arguments.length;
	var list = {};
	var rs = [];
	if (clist) {
		for (var i=0; i < clist.length; i++) {
			var c=this.getComponent(clist[i]);
			if (!zxt.util.isAvailable(c)) {
				rs.push({"ID":clist[i],"STATUS":{status:false,type:zxt.core.ValidatorType.UNDEFINED,param:null,info:""}}); 
			}else{
				list[clist[i]]=c;
			}
		}
	}else{
		list = this.components();
	}
	
	
	for (var m in list) {
		var co = this.getComponent(m);
		if (zxt.util.isAvailable(co.validateStatus())&&co.validateStatus().status==false) {
			var map = {"ID":m,"STATUS":co.validateStatus()};
			rs.push(map);
		};
	};
	
	return rs;
};

zxt.Page.INSTANCE = new zxt.Page();
/**
 *<p>
 * 每一张页面拥有一个static的页面控件实例,用$zxt代表页面的zxt.Page对象
 *</p>
 * 
 * @static 页面控件实例
 */
$zxt = zxt.Page.INSTANCE;

$zxt.cfg = zxt.cfg;

/**
 *<p>
 * 每一张页面拥有一个static的页面中所有已注册控件数组的实例
 *</p>
 * 
 * @static 页面中所有已注册控件数组的实例
 */
$zxtUI = zxt.Page.INSTANCE.components();

/**
 * <p>设置页面Token标记</p>
 * @function
 * @param t Token序列标记
 */
$zxt.setToken = function(t){
	$zxt.token = t;
};

/**
 * <p>获取Token标记</p>
 * @function
 */
$zxt.getToken = function(){
	return $zxt.token;
};